#ifndef xpack_lang_cxx_make_uri
#define xpack_lang_cxx_make_uri
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::lang_cxx::inc
#include"define/base_type.hpp"
#include"interface/unified_seq.hpp"
#include"lang/cxx/private/lut.uri.hpp"
#include"lang/cxx/encode_first_as.hpp"
#include"lang/cxx.hpp"
#include"lang/wxx/length_if_as_utf8.hpp"
#include"lang/wxx.hpp"
#include"macro/xforward.hpp"
#include"macro/xunlikely.hpp"
#include"meta/char_type.hpp"
#include"meta/unsigned_type.hpp"
#pragma pop_macro("xuser")

namespace mixc::lang_cxx{
    template<class item_t>
    inline void make_uri_core(uri_t const & convert_free, auto const & seq, auto const & alloc){
        using char_t            = inc::char_type<decltype(seq[0])>;
        using unsigned_t        = inc::unsigned_type<char_t>;
        enum{ max_buffer = 3 };
        item_t buffer[max_buffer];
        auto total_length       = uxx(0);

        for(uxx i = 0, len = seq->length; i < len; i++){
            if (auto item = unsigned_t(seq[i]); sizeof(item) > 1 and item > 255){
                total_length   += 3/*%xx 三个字符*/ * inc::wxx<char_t>{ char_t(seq[i]) }->length_if_as_utf8;
            }
            else if (item >= 128 or convert_free[item] == false){
                total_length   += 3;    // %xx 三个字符
            }
            else{
                total_length   += 1;
            }
        }

        auto stream             = alloc(total_length);

        xunlikely(stream == nullptr){
            return;
        }

        auto hex_lut            = "0123456789ABCDEF";
        auto encode             = [&](auto buffer, auto source, uxx length){
            for(uxx i = 0; i < length; i++){
                auto item       = u08(source[i]);
                buffer[0]       = '%';
                buffer[1]       = hex_lut[item >> 4];
                buffer[2]       = hex_lut[item & 0xf];
                stream.output(buffer, max_buffer);
            }
        };
        
        for(uxx i = 0, len = seq->length; i < len; i++){
            if (auto item = unsigned_t(seq[i]); sizeof(item) > 1 and item > 255){
                auto c          = char_t(seq[i]);
                auto one        = inc::cxx<char_t>{ & c, 1 };
                auto utf8       = one.template encode_first_as<char>();
                encode(buffer, utf8, utf8->length);
            }
            else if (item >= 128 or convert_free[item] == false){
                encode(buffer, & item, 1);
            }
            else{
                stream.output(item);
            }
        }
    }

    template<class item_t>
    template<inc::can_unified_seqlize seq_t, class xalloc_t, class ret_t, class>
    requires(sizeof(inc::item_origin_of<seq_t>) <= 4)
    inline cxx<item_t>::cxx(uri_t const & mode, seq_t && seq, xalloc_t const & alloc) : cxx<item_t>(){
        auto source         = inc::unified_seq<seq_t>(xforward(seq));
        auto allocx         = the_t::helper::stream_helper(alloc, xmodify(m_ptr), xmodify(m_length));
        make_uri_core<item_t>(mode, source, allocx);
    }
}

#endif
